C.S.Burner 🪙 ━►🔥GIT Node
meshchatx/src/backend/database/provider.py master (f0f6ed57) Text, 13.93 KB
T8b949e# SPDX-License-Identifier: 0BSD
Tff7b72import T7ee787sqlite3
Tff7b72import T7ee787sys
Tff7b72import T7ee787threading
Tff7b72import T7ee787time
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787databaseT7ee787.T7ee787sqlite_errors Tff7b72import Te6edf3sqlite_error_is_retryable
Te6edf3_SQLITE_CONNECT_KW Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72if Te6edf3sysTff7b72.Td2a8ffversion_info Tff7b72>Tff7b72= Tb4b4b4(T79c0ff3Tb4b4b4, T79c0ff14Tb4b4b4)Tb4b4b4:
Te6edf3_SQLITE_CONNECT_KWTb4b4b4[Ta5d6ff"Ta5d6ffcached_statementsTa5d6ff"Tb4b4b4] Tff7b72= T79c0ff100
Te6edf3_SQLITE_BUSY_TIMEOUT_MS Tff7b72= T79c0ff5000
T8b949e# Warn-only. Live threads keep their connections. Dead-thread and ident-reuse
T8b949e# cleanup is what stops announce-flood FD growth. Never close another live
T8b949e# thread's handle (that caused HTTP 500 "Cannot operate on a closed database").
Te6edf3_WARN_CONNECTIONS Tff7b72= T79c0ff256
Tff7b72class T56d364DatabaseProviderTb4b4b4:
Te6edf3_instance Tff7b72= Tff7b72None
Te6edf3_lock Tff7b72= Te6edf3threadingTff7b72.Td2a8ffRLockTb4b4b4(Tb4b4b4)
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3db_pathTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdb_path Tff7b72= Te6edf3db_path
Tff7b72selfTff7b72.Td2a8ff_local Tff7b72= Te6edf3threadingTff7b72.Td2a8fflocalTb4b4b4(Tb4b4b4)
T8b949e# conn -> {"thread_ident": int | None, "last_used": float}
Tff7b72selfTff7b72.Td2a8ff_connection_metaTb4b4b4: Tffa657dictTb4b4b4[Te6edf3sqlite3Tff7b72.Td2a8ffConnectionTb4b4b4, Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_by_identTb4b4b4: Tffa657dictTb4b4b4[Tffa657intTb4b4b4, Te6edf3sqlite3Tff7b72.Td2a8ffConnectionTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_close_generation Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ff_memory_connection Tff7b72= Tff7b72None
T8b949e# Per-connection default. Worker threads opened via asyncio.to_thread
T8b949e# never see Database._tune_sqlite_pragmas(), so this must be set here.
T8b949e# FILE temp under Landlock often fails with "unable to open database file"
T8b949e# when SQLite spills sort/hash work for large conversation queries.
Tff7b72selfTff7b72.Td2a8ffprefer_temp_store_file Tff7b72= Tff7b72False
Tf0883e@property
Tff7b72def Td2a8ff_connectionsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Compatibility alias for older callers and tests."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_connection_metaTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffconnection_countTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72return Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_connection_metaTb4b4b4)
Tff7b72def Td2a8ff_configure_connectionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3connectionTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3connection Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffPRAGMA busy_timeout=Tffd700{Te6edf3_SQLITE_BUSY_TIMEOUT_MSTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffOperationalErrorTb4b4b4:
Tff7b72pass
Tff7b72tryTb4b4b4:
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA journal_mode=WALTa5d6ff"Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffOperationalErrorTb4b4b4:
Tff7b72pass
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffprefer_temp_store_fileTb4b4b4:
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA temp_store=FILETa5d6ff"Tb4b4b4)
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA cache_size=-2000Ta5d6ff"Tb4b4b4)
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA mmap_size=0Ta5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA temp_store=MEMORYTa5d6ff"Tb4b4b4)
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA cache_size=-8000Ta5d6ff"Tb4b4b4)
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA mmap_size=67108864Ta5d6ff"Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffOperationalErrorTb4b4b4:
Tff7b72pass
Tff7b72tryTb4b4b4:
Te6edf3connectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA synchronous=NORMALTa5d6ff"Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffOperationalErrorTb4b4b4:
Tff7b72pass
Tff7b72def Td2a8ff_connection_usableTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3connTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72if Te6edf3conn Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72if Te6edf3conn Tff7b72not Tff7b72in Tff7b72selfTff7b72.Td2a8ff_connection_metaTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72tryTb4b4b4:
Te6edf3connTff7b72.Td2a8ffin_transaction
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffProgrammingErrorTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tff7b72True
Tff7b72def Td2a8ff_close_tracked_connectionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3connTb4b4b4: Te6edf3sqlite3Tff7b72.Td2a8ffConnectionTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3meta Tff7b72= Tff7b72selfTff7b72.Td2a8ff_connection_metaTff7b72.Td2a8ffpopTb4b4b4(Te6edf3connTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3meta Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3ident Tff7b72= Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffthread_identTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3ident Tff7b72is Tff7b72not Tff7b72None Tff7b72and Tff7b72selfTff7b72.Td2a8ff_by_identTff7b72.Td2a8ffgetTb4b4b4(Te6edf3identTb4b4b4) Tff7b72is Te6edf3connTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_by_identTff7b72.Td2a8ffpopTb4b4b4(Te6edf3identTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3connTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72tryTb4b4b4:
Te6edf3connTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72def Td2a8ff_drop_local_connectionTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3conn Tff7b72= Tffa657getattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffconnectionTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3conn Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_close_tracked_connectionTb4b4b4(Te6edf3connTb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffconnectionTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72del Tff7b72selfTff7b72.Td2a8ff_localTff7b72.Td2a8ffconnection
Tff7b72def Td2a8ffprune_orphaned_connectionsTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Close connections whose owning thread is no longer alive."""
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_prune_orphaned_connections_unlockedTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_prune_orphaned_connections_unlockedTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
Te6edf3alive Tff7b72= Tb4b4b4{Te6edf3tTff7b72.Td2a8ffident Tff7b72for Te6edf3t Tff7b72in Te6edf3threadingTff7b72.Td2a8ffenumerateTb4b4b4(Tb4b4b4) Tff7b72if Te6edf3tTff7b72.Td2a8ffident Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4}
Te6edf3dropped Tff7b72= T79c0ff0
Tff7b72for Te6edf3identTb4b4b4, Te6edf3conn Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_by_identTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3ident Tff7b72in Te6edf3aliveTb4b4b4:
Tff7b72continue
Tff7b72selfTff7b72.Td2a8ff_close_tracked_connectionTb4b4b4(Te6edf3connTb4b4b4)
Te6edf3dropped Tff7b72+Tff7b72= T79c0ff1
T8b949e# Connections missing from _by_ident (should not happen) still leak FDs.
Tff7b72for Te6edf3connTb4b4b4, Te6edf3meta Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_connection_metaTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3tid Tff7b72= Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffthread_identTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3tid Tff7b72is Tff7b72None Tff7b72or Te6edf3tid Tff7b72not Tff7b72in Te6edf3aliveTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_close_tracked_connectionTb4b4b4(Te6edf3connTb4b4b4)
Te6edf3dropped Tff7b72+Tff7b72= T79c0ff1
Tff7b72return Te6edf3dropped
Tff7b72def Td2a8ff_track_connectionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3connTb4b4b4: Te6edf3sqlite3Tff7b72.Td2a8ffConnectionTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3ident Tff7b72= Te6edf3threadingTff7b72.Td2a8ffget_identTb4b4b4(Tb4b4b4)
Te6edf3old Tff7b72= Tff7b72selfTff7b72.Td2a8ff_by_identTff7b72.Td2a8ffgetTb4b4b4(Te6edf3identTb4b4b4)
Tff7b72if Te6edf3old Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3old Tff7b72is Tff7b72not Te6edf3connTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_close_tracked_connectionTb4b4b4(Te6edf3oldTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_by_identTb4b4b4[Te6edf3identTb4b4b4] Tff7b72= Te6edf3conn
Tff7b72selfTff7b72.Td2a8ff_connection_metaTb4b4b4[Te6edf3connTb4b4b4] Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffthread_identTa5d6ff"Tb4b4b4: Te6edf3identTb4b4b4,
Ta5d6ff"Ta5d6fflast_usedTa5d6ff"Tb4b4b4: Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72def Td2a8ff_touch_connectionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3connTb4b4b4: Te6edf3sqlite3Tff7b72.Td2a8ffConnectionTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3meta Tff7b72= Tff7b72selfTff7b72.Td2a8ff_connection_metaTff7b72.Td2a8ffgetTb4b4b4(Te6edf3connTb4b4b4)
Tff7b72if Te6edf3meta Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6fflast_usedTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3timeTff7b72.Td2a8ffmonotonicTb4b4b4(Tb4b4b4)
Te6edf3metaTb4b4b4[Ta5d6ff"Ta5d6ffthread_identTa5d6ff"Tb4b4b4] Tff7b72= Te6edf3threadingTff7b72.Td2a8ffget_identTb4b4b4(Tb4b4b4)
Tf0883e@classmethod
Tff7b72def Td2a8ffget_instanceTb4b4b4(Tff7b72clsTb4b4b4, Te6edf3db_pathTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72clsTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72clsTff7b72.Td2a8ff_instance Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3db_path Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffDatabase path must be provided for the first initializationTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72clsTff7b72.Td2a8ff_instance Tff7b72= Tff7b72clsTb4b4b4(Te6edf3db_pathTb4b4b4)
Tff7b72elif Te6edf3db_path Tff7b72is Tff7b72not Tff7b72None Tff7b72and Tff7b72clsTff7b72.Td2a8ff_instanceTff7b72.Td2a8ffdb_path Tff7b72!= Te6edf3db_pathTb4b4b4:
Tff7b72clsTff7b72.Td2a8ff_instanceTff7b72.Td2a8ffclose_allTb4b4b4(Tb4b4b4)
Tff7b72clsTff7b72.Td2a8ff_instance Tff7b72= Tff7b72clsTb4b4b4(Te6edf3db_pathTb4b4b4)
Tff7b72return Tff7b72clsTff7b72.Td2a8ff_instance
Tff7b72def Td2a8ff_open_file_connectionTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Te6edf3sqlite3Tff7b72.Td2a8ffConnectionTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdb_path Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffdb_path is required for database connectionsTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_prune_orphaned_connections_unlockedTb4b4b4(Tb4b4b4)
Te6edf3conn Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffconnectTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4,
Te6edf3timeoutTff7b72=T79c0ff30.0Tb4b4b4,
Te6edf3check_same_threadTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3isolation_levelTff7b72=Tff7b72NoneTb4b4b4,
Tff7b72*Tff7b72*Te6edf3_SQLITE_CONNECT_KWTb4b4b4,
Tb4b4b4)
Te6edf3connTff7b72.Td2a8ffrow_factory Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffRow
Tff7b72selfTff7b72.Td2a8ff_configure_connectionTb4b4b4(Te6edf3connTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_localTff7b72.Td2a8ffconnection Tff7b72= Te6edf3conn
Tff7b72selfTff7b72.Td2a8ff_localTff7b72.Td2a8ffgeneration Tff7b72= Tff7b72selfTff7b72.Td2a8ff_close_generation
Tff7b72selfTff7b72.Td2a8ff_track_connectionTb4b4b4(Te6edf3connTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_connection_metaTb4b4b4) Tff7b72> Te6edf3_WARN_CONNECTIONSTb4b4b4:
Tff7b72import T7ee787logging
Te6edf3loggingTff7b72.Td2a8ffgetLoggerTb4b4b4(Ta5d6ff"Ta5d6ffmeshchatx.databaseTa5d6ff"Tb4b4b4)Tff7b72.Td2a8ffwarningTb4b4b4(
Ta5d6ff"Ta5d6ffSQLite connection count Tffd700%sTa5d6ff exceeds Tffd700%sTa5d6ff live-thread handlesTa5d6ff"Tb4b4b4,
Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_connection_metaTb4b4b4)Tb4b4b4,
Te6edf3_WARN_CONNECTIONSTb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3conn
Tf0883e@property
Tff7b72def Td2a8ffconnectionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# In-memory databases are private to the connection.
T8b949e# If we use threading.local(), each thread gets a DIFFERENT in-memory database.
T8b949e# For :memory:, we must share the connection across threads.
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdb_path Tff7b72== Ta5d6ff"Ta5d6ff:memory:Ta5d6ff"Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_memory_connection Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_memory_connection Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_memory_connection Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffconnectTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4,
Te6edf3check_same_threadTff7b72=Tff7b72FalseTb4b4b4,
Te6edf3isolation_levelTff7b72=Tff7b72NoneTb4b4b4,
Tff7b72*Tff7b72*Te6edf3_SQLITE_CONNECT_KWTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_memory_connectionTff7b72.Td2a8ffrow_factory Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffRow
Tff7b72selfTff7b72.Td2a8ff_configure_connectionTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_memory_connectionTb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_memory_connection
Te6edf3local_gen Tff7b72= Tffa657getattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffgenerationTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3local_conn Tff7b72= Tffa657getattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffconnectionTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Te6edf3local_conn Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3local_gen Tff7b72== Tff7b72selfTff7b72.Td2a8ff_close_generationTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_connection_usableTb4b4b4(Te6edf3local_connTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_touch_connectionTb4b4b4(Te6edf3local_connTb4b4b4)
Tff7b72return Te6edf3local_conn
Tff7b72selfTff7b72.Td2a8ff_close_tracked_connectionTb4b4b4(Te6edf3local_connTb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffconnectionTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72del Tff7b72selfTff7b72.Td2a8ff_localTff7b72.Td2a8ffconnection
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3local_gen Tff7b72= Tffa657getattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffgenerationTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3local_conn Tff7b72= Tffa657getattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffconnectionTa5d6ff"Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72if Tb4b4b4(
Te6edf3local_conn Tff7b72is Tff7b72not Tff7b72None
Tff7b72and Te6edf3local_gen Tff7b72== Tff7b72selfTff7b72.Td2a8ff_close_generation
Tff7b72and Tff7b72selfTff7b72.Td2a8ff_connection_usableTb4b4b4(Te6edf3local_connTb4b4b4)
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_touch_connectionTb4b4b4(Te6edf3local_connTb4b4b4)
Tff7b72return Te6edf3local_conn
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_open_file_connectionTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ff_call_with_reconnectTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3fnTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72return Te6edf3fnTb4b4b4(Tb4b4b4)
Tff7b72except Tb4b4b4(Te6edf3sqlite3Tff7b72.Td2a8ffProgrammingErrorTb4b4b4, Te6edf3sqlite3Tff7b72.Td2a8ffOperationalErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Tff7b72if Tff7b72not Te6edf3sqlite_error_is_retryableTb4b4b4(Te6edf3excTb4b4b4)Tb4b4b4:
Tff7b72raise
Tff7b72selfTff7b72.Td2a8ff_drop_local_connectionTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3fnTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffexecuteTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3queryTb4b4b4, Te6edf3paramsTff7b72=Tff7b72NoneTb4b4b4, Te6edf3commitTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ff_runTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3cursor Tff7b72= Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffcursorTb4b4b4(Tb4b4b4)
T8b949e# Convert any datetime objects in params to ISO strings to avoid DeprecationWarning in Python 3.12+
Tff7b72if Te6edf3paramsTb4b4b4:
Tff7b72from T7ee787datetime Tff7b72import Te6edf3datetime
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3paramsTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3bound Tff7b72= Tb4b4b4{
Te6edf3kTb4b4b4: Tb4b4b4(Te6edf3vTff7b72.Td2a8ffisoformatTb4b4b4(Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3vTb4b4b4, Te6edf3datetimeTb4b4b4) Tff7b72else Te6edf3vTb4b4b4)
Tff7b72for Te6edf3kTb4b4b4, Te6edf3v Tff7b72in Te6edf3paramsTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72elseTb4b4b4:
Te6edf3bound Tff7b72= Tffa657tupleTb4b4b4(
Tb4b4b4(Te6edf3pTff7b72.Td2a8ffisoformatTb4b4b4(Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3pTb4b4b4, Te6edf3datetimeTb4b4b4) Tff7b72else Te6edf3pTb4b4b4)
Tff7b72for Te6edf3p Tff7b72in Te6edf3params
Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3bound Tff7b72= Tff7b72None
Tff7b72if Te6edf3boundTb4b4b4:
Te6edf3cursorTff7b72.Td2a8ffexecuteTb4b4b4(Te6edf3queryTb4b4b4, Te6edf3boundTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3cursorTff7b72.Td2a8ffexecuteTb4b4b4(Te6edf3queryTb4b4b4)
T8b949e# In autocommit mode (isolation_level=None), in_transaction is True
T8b949e# only if we explicitly started one with BEGIN and haven't committed/rolled back.
Tff7b72if Te6edf3commit Tff7b72is Tff7b72TrueTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72elif Te6edf3commit Tff7b72is Tff7b72FalseTb4b4b4:
Tff7b72pass
T8b949e# Default behavior: if we're in a manual transaction, don't commit automatically
Tff7b72elif Tff7b72not Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffin_transactionTb4b4b4:
T8b949e# In autocommit mode, non-DML statements don't start transactions.
T8b949e# DML statements might if they are part of a BEGIN block.
T8b949e# Actually, in isolation_level=None, NOTHING starts a transaction unless we say BEGIN.
Tff7b72pass
Tff7b72return Te6edf3cursor
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_call_with_reconnectTb4b4b4(Te6edf3_runTb4b4b4)
Tff7b72def Td2a8ffbeginTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ff_runTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# IMMEDIATE acquires a reserved lock up front so concurrent writers wait
T8b949e# on busy_timeout instead of failing with "database is locked" at commit.
Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffBEGIN IMMEDIATETa5d6ff"Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffOperationalError Tff7b72as Te6edf3eTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ffwithin a transactionTa5d6ff" Tff7b72in Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4:
Tff7b72pass
Tff7b72elseTb4b4b4:
Tff7b72raise
Tff7b72selfTff7b72.Td2a8ff_call_with_reconnectTb4b4b4(Te6edf3_runTb4b4b4)
Tff7b72def Td2a8ffcommitTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffin_transactionTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffrollbackTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffin_transactionTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffrollbackTb4b4b4(Tb4b4b4)
Tff7b72def Tff7b72__enter__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffbeginTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72self
Tff7b72def Tff7b72__exit__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3exc_typeTb4b4b4, Te6edf3exc_valTb4b4b4, Te6edf3exc_tbTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3exc_typeTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrollbackTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72def Td2a8ffexecutemanyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3queryTb4b4b4, Te6edf3params_seqTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ff_runTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3cursor Tff7b72= Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffcursorTb4b4b4(Tb4b4b4)
Te6edf3cursorTff7b72.Td2a8ffexecutemanyTb4b4b4(Te6edf3queryTb4b4b4, Te6edf3params_seqTb4b4b4)
Tff7b72return Te6edf3cursor
Tff7b72return Tff7b72selfTff7b72.Td2a8ff_call_with_reconnectTb4b4b4(Te6edf3_runTb4b4b4)
Tff7b72def Td2a8fffetchoneTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3queryTb4b4b4, Te6edf3paramsTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3cursor Tff7b72= Tff7b72selfTff7b72.Td2a8ffexecuteTb4b4b4(Te6edf3queryTb4b4b4, Te6edf3paramsTb4b4b4)
Te6edf3row Tff7b72= Te6edf3cursorTff7b72.Td2a8fffetchoneTb4b4b4(Tb4b4b4)
Tff7b72return Tffa657dictTb4b4b4(Te6edf3rowTb4b4b4) Tff7b72if Te6edf3row Tff7b72else Tff7b72None
Tff7b72def Td2a8fffetchallTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3queryTb4b4b4, Te6edf3paramsTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
Te6edf3cursor Tff7b72= Tff7b72selfTff7b72.Td2a8ffexecuteTb4b4b4(Te6edf3queryTb4b4b4, Te6edf3paramsTb4b4b4)
Te6edf3rows Tff7b72= Te6edf3cursorTff7b72.Td2a8fffetchallTb4b4b4(Tb4b4b4)
Tff7b72return Tb4b4b4[Tffa657dictTb4b4b4(Te6edf3rowTb4b4b4) Tff7b72for Te6edf3row Tff7b72in Te6edf3rowsTb4b4b4]
Tff7b72def Td2a8ffcloseTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdb_path Tff7b72== Ta5d6ff"Ta5d6ff:memory:Ta5d6ff" Tff7b72and Tff7b72selfTff7b72.Td2a8ff_memory_connectionTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_memory_connectionTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_memory_connectionTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72selfTff7b72.Td2a8ff_memory_connection Tff7b72= Tff7b72None
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffconnectionTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3conn Tff7b72= Tff7b72selfTff7b72.Td2a8ff_localTff7b72.Td2a8ffconnection
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_close_tracked_connectionTb4b4b4(Te6edf3connTb4b4b4)
Tff7b72del Tff7b72selfTff7b72.Td2a8ff_localTff7b72.Td2a8ffconnection
Tff7b72def Td2a8ffclose_allTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_close_generation Tff7b72+Tff7b72= T79c0ff1
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_memory_connectionTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_memory_connectionTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_memory_connectionTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72pass
Tff7b72selfTff7b72.Td2a8ff_memory_connection Tff7b72= Tff7b72None
Tff7b72for Te6edf3conn Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_connection_metaTff7b72.Td2a8ffkeysTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_close_tracked_connectionTb4b4b4(Te6edf3connTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_connection_metaTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_by_identTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_localTb4b4b4, Ta5d6ff"Ta5d6ffconnectionTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72del Tff7b72selfTff7b72.Td2a8ff_localTff7b72.Td2a8ffconnection
Tff7b72def Td2a8ffvacuumTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# VACUUM cannot run inside a transaction
Tff7b72selfTff7b72.Td2a8ffcommitTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffconnectionTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffVACUUMTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffintegrity_checkTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8fffetchallTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA integrity_checkTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffquick_checkTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8fffetchallTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA quick_checkTa5d6ff"Tb4b4b4)
Tff7b72def Td2a8ffcheckpointTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8fffetchallTb4b4b4(Ta5d6ff"Ta5d6ffPRAGMA wal_checkpoint(TRUNCATE)Ta5d6ff"Tb4b4b4)
Served by rngit 1.4.2 - Generated in 0.03s